package com.luo.sc.oidc.authserver.enums;

import org.springframework.security.crypto.argon2.Argon2PasswordEncoder;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.NoOpPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.crypto.password.Pbkdf2PasswordEncoder;
import org.springframework.security.crypto.scrypt.SCryptPasswordEncoder;

import java.util.HashMap;
import java.util.Map;

/**
 * 密码编码器枚举
 *
 * @author luohq
 * @version 1.0.0
 * @date 2022-02-21 11:10
 */
public enum PasswordEncoderEnum {
    //bcrypt算法及实现
    BCRYPT("bcrypt", new BCryptPasswordEncoder()),
    //pbkdf2算法及实现
    PBKDF2("pbkdf2", new Pbkdf2PasswordEncoder()),
    //scrypt算法及实现
    SCRYPT("scrypt", new SCryptPasswordEncoder()),
    //argon2算法及实现
    ARGON2("argon2", new Argon2PasswordEncoder()),
    //无转换算法
    NOOP("noop", NoOpPasswordEncoder.getInstance());

    /**
     * 加密算法ID
     */
    private String id;
    /**
     * 加密算法实现
     */
    private PasswordEncoder passwordEncoder;

    /**
     * 构造枚举
     *
     * @param id              加密算法ID
     * @param passwordEncoder 加密算法实现
     */
    PasswordEncoderEnum(String id, PasswordEncoder passwordEncoder) {
        this.id = id;
        this.passwordEncoder = passwordEncoder;
    }

    /**
     * 根据ID获取密码编码器枚举（默认BCRYPT）
     *
     * @param id 算法ID
     * @return 密码编码器枚举
     */
    public static PasswordEncoderEnum getDefaultPasswordEncoderEnum(String id) {
        for (PasswordEncoderEnum curEnum : PasswordEncoderEnum.values()) {
            if (curEnum.getId().equals(id)) {
                return curEnum;
            }
        }
        return BCRYPT;
    }

    /**
     * 转换当前枚举为Map(id, PasswordEncoder)
     *
     * @return Map(id, PasswordEncoder)
     */
    public static Map<String, PasswordEncoder> toIdToPasswordEncoderMap() {
        Map<String, PasswordEncoder> encoders = new HashMap<>();
        for (PasswordEncoderEnum curEnum : PasswordEncoderEnum.values()) {
            encoders.put(curEnum.getId(), curEnum.getPasswordEncoder());
        }
        return encoders;
    }

    public String getId() {
        return id;
    }

    public PasswordEncoder getPasswordEncoder() {
        return passwordEncoder;
    }

}
